#!/usr/bin/python
# $Id$
# Change to keep on for 20 seconds

import os, sys
import pygame
import math
from pygame.locals import *
from sys import exit
import random

import Tkinter
from Tkinter import *

import time

class ScoreBoard:
	def __init__(self, master, current_score):
		try:
			score_f = open("score", "rb")
			f.seek(0)
			try:
				name_old = score_f.readline()
				score_old = score_f.readline()
				time_old = score_f.readline()
			except IOError:
				name = ''
				score = 0

			name = 'qsun'
			score = current_score
			time = time.localtime(time.time())
			print 'name is ', name
			print 'score is ', score
			print 'time is ', time

			frame = Frame(master)
			frame.pack()
			self.score_txt = Label(frame, text = "Highest score:\nYour score is:\n")
			self.score_txt.pack(side = TOP)
			self.button_upload = Button(frame, text = "Upload", fg = "red", command = self.upload)
			self.button_upload.pack(side = LEFT)
			self.button_quit = Button(frame, text = "Quit", fg = "red", command = self.quit)
			self.button_quit.pack(side = RIGHT)
		except IOError:
			print 'IOError'
			sys.exit(0)

	def upload(self):
		# TODO
		print 'Uploading'
	def quit(self):
		print 'quit'
		sys.exit(0)

def lose(score):
	root = Tk()
	score_board = ScoreBoard(root, score)
	root.mainloop()

score = 0

tank_speed = 3 # The normal movement speed of tank(player tank), 3 pixels per frame, 60 frames per second
collision_distance_square = 10 * 10 # Minimal distance of collision
bullet_speed = 1 # The normal movement speed of bullet

x_boundary = 400 # The width of playground
y_boundary = 400 # The hight of playground

n_bullets = 10 # number of bullets

lose_tita = 0 # Lose, display original frame in the next 3 seconds, then switch to score board

spirites_array = []

pygame.font.init()

font_path = 'cour.ttf'
font = pygame.font.Font(font_path, 30)

disp_string = ''
lost_flag = False

def game_over():
	global disp_string
	global lost_flag
	print 'game_over'
	disp_string = "SCORE: " + str(score)
	lost_flag = True

# Loading a given picture into memory
def load_image(name, colorkey = None):
	fullname = os.path.join(name); # Describe the full path of fullname of tank. This should be fixed in next version
	try:
		print 'Loading picture: ', fullname
		image = pygame.image.load(fullname)
	except pygame.error, message:
		print '''cannot load image: ''', name
		raise SystemExit, message
	image = image.convert()
	if colorkey is not None:
		if colorkey is -1:
			colorkey = image.get_at((0,0))
			image.set_colorkey(colorkey, RLEACCEL)
	return image, image.get_rect()

# Get the distance from a point to another point
def distance_square(frm, to):
	return (frm[0] - to[0]) ** 2 + (frm[1] - to[1]) ** 2

def random_generate_bullets():
	if len(spirites_array) > n_bullets:
		return
	from_x = 0
	from_y = 0
	target_x, target_y = my_tank.rect.center
	rnd = random.randint(0, 3)
	if rnd == 0:
		from_x = random.randint(0, x_boundary)
		from_y = 0
	elif rnd == 1:
		from_x = 0
		from_y = random.randint(0, y_boundary)
	elif rnd == 2:
		from_x = random.randint(0, x_boundary)
		from_y = y_boundary
	else:
		from_x = x_boundary
		from_y = random.randint(0, y_boundary)
	bullet = Bullet(from_x, from_y, target_x, target_y, 'bullet')
	spirites_array.append(bullet)

# Tank class
class Tank(pygame.sprite.Sprite):
	"""Tank"""
	def get_identification(self):
		return self.identification
	def __init__(self):
		self.identification = (1, 0)
		pygame.sprite.Sprite.__init__(self)
		self.image, self.rect = load_image('tank.bmp', -1)
		# Initial position
		self.x_boundary = x_boundary 
		self.y_boundary = y_boundary
		self.x = self.x_boundary / 2
		self.y = self.y_boundary / 2
		self.shoot_state = 0
		self.next_shoot_state = 0
		self.last_shoot_cooldown = 0
		self.slot_n_bullets = 5
		#print self.rect.center
		self.rect.center = (self.x, self.y)
		#print self.rect.center

	def start_shoot(self):
		self.shoot_state = 1

	def stop_shoot(self):
		self.next_shoot_state = 0

	def shoot(self):
		'''
		print 'trying to shoot, cool down state is: ', self.last_shoot_cooldown
		if self.slot_n_bullets > 0 and self.last_shoot_cooldown == 0:
			self.target = pygame.mouse.get_pos()
			print 'shoot to: ', self.target
			bullet = Bullet(self.x, self.y, self.target[0], self.target[1], 'self')
			spirites_array.append(bullet)
			self.last_shoot_cooldown = 40
			self.slot_n_bullets -= 1
		'''
		return

	def reload(self):
		print 'reload gun'
		if self.last_shoot_cooldown < 10:
			self.last_shoot_cooldown = 80
			self.slot_n_bullets = 5

	def update_shoot_cooldown(self):
		#print 'cooling down', self.last_shoot_cooldown
		if self.last_shoot_cooldown > 0:
			self.last_shoot_cooldown -= 1
			#print 'cooling down'

	def getPos(self):
		return (self.x, self.y)

	def update(self):
		#print 'cooling down state: ', self.last_shoot_cooldown
		self.update_shoot_cooldown()
		if self.shoot_state == 1:
			self.shoot()
		if self.next_shoot_state == 0:
			self.shoot_state = 0
			self.next_shoot_state = 1
		#print 'Let me move!'

	def move(self, x_axis, y_axis):
		if x_axis == 0 and y_axis == 0:
			return

		if x_axis != 0 and y_axis != 0:
			x_axis = x_axis / 1.414
			y_axis = y_axis / 1.414

		x_axis = tank_speed * x_axis
		y_axis = tank_speed * y_axis
		self.x += x_axis
		self.y += y_axis

		# rule these values
		if self.x < 0:
			self.x = 0
		if self.y < 0:
			self.y = 0
		if self.x >= self.x_boundary:
			self.x = self.x_boundary
		if self.y >= self.y_boundary:
			self.y = self.y_boundary
		
		self.rect.center = (self.x, self.y)
		#print 'x is ', self.x
		#print 'y is ', self.y
		#print 'move image to x: ', self.x, ' y: ', self.y

class Bullet(pygame.sprite.Sprite):
	"""Bullet class"""
	def get_identification(self):
		return self.identification
	def __init__(self, x, y, to_x, to_y, owner): # x, y: The position of initial of bullet; to_x, to_y:  The position of virtual target; owner: ownership of this bullet
		self.identification = (0, 0)
		pygame.sprite.Sprite.__init__(self) 
		self.image, self.rect = load_image('bullet.png', -1)
		self.from_pos = (x, y)
		self.to_pos = (to_x, to_y)
		self.rect.center = (x, y) # This is the initial position of bullet
		self.owner = owner
		#self.toward_vector = (to_x - x, to_y - y)
		distance = math.sqrt(distance_square((to_x, to_y), (x, y)))
		x_vector = (to_x - x) / distance
		y_vector = (to_y - y) / distance
		self.movement_vector = [x_vector, y_vector]
		return
	def update(self):
		x, y = self.from_pos
		if x < 0 or x > x_boundary or y < 0 or y > y_boundary:
			spirites_array.remove(self)
			return
		x = x + self.movement_vector[0] * bullet_speed
		y = y + self.movement_vector[1] * bullet_speed
		self.from_pos = (x, y)
		self.rect.center = (x, y)
		#print 'distance: ', distance
		# print 'x, y: ', x, ' ', y
		self.collision()
		return 
	def collision(self):
		#print 'n_spirites: ', spirites_array
		dist = distance_square(self.rect.center, my_tank.rect.center)

		if dist < collision_distance_square:
			print 'Collision'
			game_over()
			print 'after collision, state: ', lost_flag
			if my_tank in spirites_array:
				spirites_array.remove(my_tank)
			spirites_array.remove(self)
		return

pygame.init()
screen = pygame.display.set_mode((x_boundary, y_boundary))
pygame.display.set_caption('Tank Game')
#pygame.mounse.set_visible(0)

my_tank = Tank()
#my_tank.identification = (my_tank.identification[0], 1)
#enemy_tank = Tank()

spirites_array.append(my_tank)

allspirites = pygame.sprite.RenderPlain(spirites_array)
print allspirites
clock = pygame.time.Clock()

right_down = 0
left_down = 0
up_down = 0
down_down = 0

# set key repeat
pygame.key.set_repeat(30, 30)

n_cycle = 0

while 1:
	# Initial two axis
	right=0
	left=0
	up=0
	down=0

	clock.tick(60)

	if lost_flag == False:
		n_cycle = n_cycle + 1
		n_cycle = n_cycle % 60

		if n_cycle == 0:
			n_bullets = n_bullets + 1
			print score

		random_generate_bullets()
	else:
		lose_tita = lose_tita + 1
		if lose_tita > (60 * 3):
			# If lose_tita > 3 seconds, let's r'r score board
			lose(score)
			sys.exit(0)

	# Get key map
	key_states = pygame.key.get_pressed()
	
	if key_states[K_RIGHT] or key_states[K_d]:
		right = 1
	if key_states[K_LEFT] or key_states[K_a]:
		left = 1
	if key_states[K_UP] or key_states[K_w]:
		up = 1
	if key_states[K_DOWN] or key_states[K_s]:
		down = 1
	#print '''state: ''', up, down, left, right
	my_tank.move((right - left), (down - up))

	if key_states[K_q]:
		exit(0)

	for event in pygame.event.get():
		if event.type == QUIT:
			exit(0)
		if event.type == MOUSEBUTTONDOWN and event.button == 1:
			my_tank.start_shoot()
		elif event.type == MOUSEBUTTONUP and event.button == 1:
			# print 'reload'
			my_tank.stop_shoot()
		elif event.type == MOUSEBUTTONDOWN and event.button == 3: 
			# Reload gun
			my_tank.reload()
		# move the tank
	
	if lost_flag == False:
		screen.fill((0, 0, 0))
		allspirites = pygame.sprite.RenderUpdates(spirites_array)
		allspirites.update()
		allspirites.draw(screen)
		s = font.render("SCORE: " + str(score), True, (0, 255, 255))
	else:
		s = font.render(disp_string, True, (0, 255, 0))

	# print allspirites
	
	screen.blit(s, (0, 0))
	pygame.display.flip()
	pygame.display.update()
	score = score + 1

